---
title: Project Configuration
id: projects
slug: /atlas-schema/projects
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import LoginRequired from '../components/login-required.mdx'

### Project Files

Project files provide a convenient way to describe and interact with multiple
environments when working with Atlas. A project file is a file named
`atlas.hcl` and contains one or more `env` blocks. For example:

<Tabs>
<TabItem value="mysql" label="MySQL" default>

```hcl
// Define an environment named "local"
env "local" {
  // Declare where the schema definition resides.
  // Also supported: ["file://multi.hcl", "file://schema.hcl"].
  src = "file://project/schema.hcl"

  // Define the URL of the database which is managed
  // in this environment.
  url = "mysql://user:pass@localhost:3306/schema"

  // Define the URL of the Dev Database for this environment
  // See: https://atlasgo.io/concepts/dev-database
  dev = "docker://mysql/8/dev"
}

env "dev" {
  // ... a different env
}
```

</TabItem>
<TabItem value="mariadb" label="MariaDB">

```hcl
// Define an environment named "local"
env "local" {
  // Declare where the schema definition resides.
  // Also supported: ["file://multi.hcl", "file://schema.hcl"].
  src = "file://project/schema.hcl"

  // Define the URL of the database which is managed
  // in this environment.
  url = "maria://user:pass@localhost:3306/schema"

  // Define the URL of the Dev Database for this environment
  // See: https://atlasgo.io/concepts/dev-database
  dev = "docker://maria/latest/dev"
}

env "dev" {
  // ... a different env
}
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```hcl
// Define an environment named "local"
env "local" {
  // Declare where the schema definition resides.
  // Also supported: ["file://multi.hcl", "file://schema.hcl"].
  src = "file://project/schema.hcl"

  // Define the URL of the database which is managed
  // in this environment.
  url = "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable"

  // Define the URL of the Dev Database for this environment
  // See: https://atlasgo.io/concepts/dev-database
  dev = "docker://postgres/15/dev?search_path=public"
}

env "dev" {
  // ... a different env
}
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```hcl
// Define an environment named "local"
env "local" {
  // Declare where the schema definition resides.
  // Also supported: ["file://multi.hcl", "file://schema.hcl"].
  src = "file://project/schema.hcl"

  // Define the URL of the database which is managed
  // in this environment.
  url = "sqlite://file.db?_fk=1"

  // Define the URL of the Dev Database for this environment
  // See: https://atlasgo.io/concepts/dev-database
  dev = "sqlite://file?mode=memory&_fk=1"
}

env "dev" {
  // ... a different env
}
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```hcl
// Define an environment named "local"
env "local" {
  // Declare where the schema definition resides.
  // Also supported: ["file://multi.hcl", "file://schema.hcl"].
  src = "file://project/schema.hcl"

  // Define the URL of the database which is managed
  // in this environment.
  url = "sqlserver://sa:pass@remote:1433?database=master"

  // Define the URL of the Dev Database for this environment
  // See: https://atlasgo.io/concepts/dev-database
  dev = "docker://sqlserver/2022-latest"
}

env "dev" {
  // ... a different env
}
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```hcl
// Define an environment named "local"
env "local" {
  // Declare where the schema definition resides.
  // Also supported: ["file://multi.hcl", "file://schema.hcl"].
  src = "file://project/schema.hcl"

  // Define the URL of the database which is managed
  // in this environment.
  url = "clickhouse://user:pass@remote:9000/default"

  // Define the URL of the Dev Database for this environment
  // See: https://atlasgo.io/concepts/dev-database
  dev = "docker://clickhouse/23.11/default"
}

env "dev" {
  // ... a different env
}
```

</TabItem>
</Tabs>

### Flags

Once the project configuration has been defined, you can interact with it using one of the following options:

<Tabs>
<TabItem value="env" label="Env">

To run the `schema apply` command using the `prod` configuration defined in `atlas.hcl` file located in your working directory:

```shell
atlas schema apply --env prod
```

</TabItem>
<TabItem value="custom-path" label="Custom File">

To run the `schema apply` command using the `prod` configuration defined in `atlas.hcl` in arbitrary location:

```shell {2}
atlas schema apply \
  -c file://path/to/atlas.hcl \
  --env prod
```

</TabItem>
<TabItem value="global-config" label="Global Config (without --env)">

Some commands accept global configuration blocks such as [`lint`](#configure-migration-linting) and
[`diff`](#configure-diff-policy) policies. If no `env` is defined, you can instruct Atlas to explicitly use the config
file using the `-c` (or `--config`) flag:

```shell {2}
atlas migrate lint \
  -c file://path/to/atlas.hcl \
  --dir "file://path/to/migrations" \
  --dev-url "sqlite://file?mode=memory"
```

</TabItem>
</Tabs>

Will run the `schema apply` command against the database that is defined for the `local`
environment.

:::info Unlabeled `env` blocks
It is possible to define an `env` block whose name is dynamically set during command execution using the `--env` flag.
This is useful when multiple environments share the same configuration and the arguments are dynamically set during
execution:

```hcl {2}
env {
  name = atlas.env
  url = var.url
  format {
    migrate {
      apply = format(
        "{{ json . | json_merge %q }}",
        jsonencode({
          EnvName : atlas.Env
        })
      )
    }
  }
}
```

:::

### Projects with Versioned Migrations

Environments may declare a `migration` block to configure how versioned migrations
work in the specific environment:

```hcl
env "local" {
    // ..
    migration {
        // URL where the migration directory resides.
        dir = "file://migrations"
    }
}
```

Once defined, `migrate` commands can use this configuration, for example:
```shell
atlas migrate validate --env local
```
Will run the `migrate validate` command against the Dev Database defined in the
`local` environment.

### Passing Input Values

Project files may pass [input values](hcl-input.md) to variables defined in Atlas HCL schemas. To do this,
define an [`hcl_schema`](#data-source-hcl_schema) data source, pass it the input values, and then designate it as the
desired schema within the `env` block:

<Tabs>
<TabItem label="atlas.hcl" value="atlas.hcl">

```hcl
data "hcl_schema" "app" {
  path = "schema.hcl"
  vars = {
    // Variables are passed as input values to "schema.hcl".
    tenant = "ariga"
  }
}

env "local" {
  src = data.hcl_schema.app.url
  url = "sqlite://test?mode=memory&_fk=1"
}
```

</TabItem>
<TabItem label="schema.hcl" value="schema.hcl">

```hcl title="schema.hcl"
// This variable is passed as an input value from "atlas.hcl".
variable "tenant" {
  type = string
}

schema "main" {
  name = var.tenant
}
```

</TabItem>
</Tabs>

### Project Input Variables

Project files may also declare [input variables](hcl-input.md) that can be supplied to the CLI
at runtime. For example:

```hcl title="atlas.hcl"
variable "tenant" {
  type = string
}

data "hcl_schema" "app" {
  path = "schema.hcl"
  vars = {
    // Variables are passed as input values to "schema.hcl".
    tenant = var.tenant
  }
}

env "local" {
  src = data.hcl_schema.app.url
  url = "sqlite://test?mode=memory&_fk=1"
}
```
To set the value for this variable at runtime, use the `--var` flag:

```shell
atlas schema apply --env local --var tenant=rotemtam
```

It is worth mentioning that when running Atlas commands within a project using
the `--env` flag, all input values supplied at the command-line are passed only
to the project file, and not propagated automatically to children schema files.
This is done with the purpose of creating an explicit contract between the environment
and the schema file.

## Schema Arguments and Attributes

Project configuration files support different types of blocks.

### Input Variables

Project files support defining input variables that can be injected through the CLI, [read more here](hcl-input.md).

- `type` - The type constraint of a variable.
- `default` - Define if the variable is optional by setting its default value.

```hcl
variable "tenants" {
  type = list(string)
}

variable "url" {
  type    = string
  default = "mysql://root:pass@localhost:3306/"
}

variable "cloud_token" {
  type    = string
  default = getenv("ATLAS_TOKEN")
}

env "local" {
  // Reference an input variable.
  url = var.url
}
```

### Local Values

The `locals` block allows defining a list of local variables that can be reused multiple times in the project.

```hcl
locals {
  tenants  = ["tenant_1", "tenant_2"]
  base_url = "mysql://${var.user}:${var.pass}@${var.addr}"

  // Reference local values.
  db1_url  = "${local.base_url}/db1"
  db2_url  = "${local.base_url}/db2"
}
```

### Data Sources

Data sources enable users to retrieve information stored in an external service or database. The currently supported
data sources are:
- [`sql`](#data-source-sql)
- [`external`](#data-source-external)
- [`runtimevar`](#data-source-runtimevar)
- [`hcl_schema`](#data-source-hcl_schema)
- [`external_schema`](#data-source-external_schema)
- [`composite_schema`](#data-source-composite_schema)
- [`remote_dir`](#data-source-remote_dir)
- [`template_dir`](#data-source-template_dir)
- [`aws_rds_token`](#data-source-aws_rds_token)
- [`gcp_cloudsql_token`](#data-source-gcp_cloudsql_token)

:::note
Data sources are evaluated only if they are referenced by top-level blocks like `locals` or `variables`, or by the
selected environment, for instance, `atlas schema apply --env dev`.
:::

#### Data source: `sql`

The `sql` data source allows executing SQL queries on a database and using the results in the project.

##### Arguments {#data-source-sql-arguments}

- `url` - The [URL](../concepts/url.mdx) of the target database.
- `query` - Query to execute.
- `args` - Optional arguments for any placeholder parameters in the query.

##### Attributes {#data-source-sql-attributes}

- `count` - The number of returned rows.
- `values` - The returned values. e.g. `list(string)`.
- `value` - The first value in the list, or `nil`.

```hcl
data "sql" "tenants" {
  url = var.url
  query = <<EOS
SELECT `schema_name`
  FROM `information_schema`.`schemata`
  WHERE `schema_name` LIKE ?
EOS
  args = [var.pattern]
}

env "prod" {
  // Reference a data source.
  for_each = toset(data.sql.tenants.values)
  url      = urlsetpath(var.url, each.value)
}
```

#### Data source: `external`

The `external` data source allows the execution of an external program and uses its output in the project.

##### Arguments {#data-source-external-arguments}

- `program` - The first element of the string is the program to run. The remaining elements are optional command line arguments.
- `working_dir` - The working directory to run the program from. Defaults to the current working directory.

##### Attributes {#data-source-external-attributes}

- The command output is a `string` type with no attributes.

#### Usage example

```hcl title="atlas.hcl"
data "external" "dot_env" {
  program = [
    "npm",
    "run",
    "load-env.js"
  ]
}

locals {
  dot_env = jsondecode(data.external.dot_env)
}

env "local" {
  src = local.dot_env.URL
  dev = "docker://mysql/8/dev"
}
```

#### Data source: `runtimevar`

##### Arguments {#data-source-runtimevar-arguments}

- `url` - The [URL](../concepts/url.mdx) identifies the variable. See, the [CDK](https://gocloud.dev/howto/runtimevar/)
  documentation for more information.

##### Attributes {#data-source-runtimevar-attributes}

- The loaded variable is a `string` type with no attributes.

<Tabs>
<TabItem value="gcprc" label="GCP Runtime Configurator" default>

The data source uses [Application Default Credentials](https://cloud.google.com/docs/authentication/production) by default;
if you have authenticated via [`gcloud auth application-default login`](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login),
it will use those credentials.

```hcl title="atlas.hcl"
data "runtimevar" "db" {
  url = "gcpruntimeconfig://projects/<project>/configs/<config-id>/variables/<variable>?decoder=string"
}

env "dev" {
  src = "schema.hcl"
  url = "mysql://root:pass@host:3306/${data.runtimevar.db}"
}
```

#### Usage example

```shell
gcloud auth application-default login
atlas schema apply --env dev
```

```shell
GOOGLE_APPLICATION_CREDENTIALS="/path/to/credentials.json" atlas schema apply --env dev
```

</TabItem>
<TabItem value="gcpsm" label="GCP Secret Manager" default>

The data source uses [Application Default Credentials](https://cloud.google.com/docs/authentication/production) by default;
if you have authenticated via [`gcloud auth application-default login`](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login),
it will use those credentials.

```hcl title="atlas.hcl"
data "runtimevar" "pass" {
  url = "gcpsecretmanager://projects/<project>/secrets/<secret>"
}

env "dev" {
  src = "schema.hcl"
  url = "mysql://root:${data.runtimevar.pass}@host:3306/database"
}
```

#### Usage example

```shell
gcloud auth application-default login
atlas schema apply --env dev
```

```shell
GOOGLE_APPLICATION_CREDENTIALS="/path/to/credentials.json" atlas schema apply --env dev
```

</TabItem>
<TabItem value="awsps" label="AWS Parameter Store">

The data source provides two ways to work with AWS Parameter Store:
- If the `awssdk` query parameter is not set or is set to `v1`, a default AWS Session will be created with the
  SharedConfigEnable option enabled; if you have authenticated with the AWS CLI, it will use those credentials.
- If the `awssdk` query parameter is set to `v2`, the data source will create an AWS Config based on the AWS SDK V2.

```hcl title="atlas.hcl"
data "runtimevar" "db" {
  url = "awsparamstore://<name>?region=<region>&decoder=string"
}

env "dev" {
  src = "schema.hcl"
  url = "mysql://root:pass@host:3306/${data.runtimevar.db}"
}
```

:::note
It's common case when you use [the hierarchies format](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-hierarchies.html) for you parameters in AWS Parameter Store. So the `url` should
contain the path to the hierarchy, for example `awsparamstore:///production/tenant_a/password?region=<region>&decoder=string` - there are three slashes after the protocol.
:::


#### Usage example

```shell
# Default credentials reside in ~/.aws/credentials.
atlas schema apply --env dev
```

```shell
AWS_ACCESS_KEY_ID="ACCESS_ID" AWS_SECRET_ACCESS_KEY="SECRET_KEY" atlas schema apply --env dev
```

</TabItem>
<TabItem value="awssm" label="AWS Secrets Manager">

The data source provides two ways to work with AWS Secrets Manager:
- If the `awssdk` query parameter is not set or is set to `v1`, a default AWS Session will be created with the
  SharedConfigEnable option enabled; if you have authenticated with the AWS CLI, it will use those credentials.
- If the `awssdk` query parameter is set to `v2`, the data source will create an AWS Config based on the AWS SDK V2.

```hcl title="atlas.hcl"
data "runtimevar" "pass" {
  url = "awssecretsmanager://<secret>?region=<region>"
}

env "dev" {
  src = "schema.hcl"
  url = "mysql://root:${data.runtimevar.pass}@host:3306/database"
}
```

#### Usage example

```shell
# Default credentials reside in ~/.aws/credentials.
atlas schema apply --env dev
```

```shell
AWS_ACCESS_KEY_ID="ACCESS_ID" AWS_SECRET_ACCESS_KEY="SECRET_KEY" atlas schema apply --env dev
```

</TabItem>
<TabItem value="http" label="HTTP">

```hcl title="atlas.hcl"
data "runtimevar" "pass" {
  url = "http://service.com/foo.txt"
}

env "dev" {
  src = "schema.hcl"
  url = "mysql://root:${data.runtimevar.pass}@host:3306/database"
}
```

</TabItem>
<TabItem value="file" label="File">

```hcl title="atlas.hcl"
data "runtimevar" "pass" {
  url = "file:///path/to/config.txt"
}

env "dev" {
  src = "schema.hcl"
  url = "mysql://root:${data.runtimevar.pass}@host:3306/database"
}
```

</TabItem>
</Tabs>

#### Data source: `hcl_schema`

The `hcl_schema` data source allows the loading of an Atlas HCL schema from a file or directory, with optional variables.

##### Arguments {#data-source-hcl-schema-arguments}

- `path` - The path to the HCL file or directory.
- `vars` - A map of variables to pass to the HCL schema.

##### Attributes {#data-source-hcl-schema-attributes}

- `url` - The [URL](../concepts/url.mdx) of the loaded schema.


<Tabs>
<TabItem label="atlas.hcl" value="atlas.hcl">

```hcl {5-10}
variable "tenant" {
  type = string
}

data "hcl_schema" "app" {
  path = "schema.hcl"
  vars = {
    tenant = var.tenant
  }
}


env "local" {
  src = data.hcl_schema.app.url
  url = "sqlite://test?mode=memory&_fk=1"
}
```

</TabItem>
<TabItem label="schema.hcl" value="schema.hcl">

```hcl title="schema.hcl"
// This variable is passed as an input value from "atlas.hcl".
variable "tenant" {
  type = string
}

schema "main" {
  name = var.tenant
}
```

</TabItem>
</Tabs>

#### Data source: `external_schema`

The `external_schema` data source enables the import of an SQL schema from an external program into Atlas' desired state.
With this data source, users have the flexibility to represent the desired state of the database schema in any language.

##### Arguments {#data-source-external-schema-arguments}

- `program` - The first element of the string is the program to run. The remaining elements are optional command line arguments.
- `working_dir` - The working directory to run the program from. Defaults to the current working directory.

##### Attributes {#data-source-external-schema-attributes}

- `url` - The [URL](../concepts/url.mdx) of the loaded schema.

#### Usage example

By running `atlas migrate diff` with the given configuration, the external program will be executed and its loaded state
will be compared against the current state of the migration directory. In case of a difference between the two states,
a new migration file will be created with the necessary SQL statements.

```hcl title="atlas.hcl"
data "external_schema" "graph" {
  program = [
    "npm",
    "run",
    "generate-schema"
  ]
}

env "local" {
  src = data.external_schema.graph.url
  dev = "docker://mysql/8/dev"
  migration {
    dir = "file://migrations"
  }
}
```


#### Data source: `composite_schema` <LoginRequired /> {#data-source-composite_schema}

The `composite_schema` data source allows the composition of multiple Atlas schemas into a unified schema graph. This
functionality is useful when projects schemas are split across various sources such as HCL, SQL, or application ORMs.
For example, each service have its own database schema, or an ORM schema is extended or relies on other database schemas.

Referring to the `url` returned by this data source allows reading the entire project schemas as a single unit by any of
the Atlas commands, such as `migrate diff`, `schema apply`, or `schema inspect`.

##### Arguments {#data-source-composite-schema-arguments}

- `schema` - one or more **named** blocks containing the [URL](../concepts/url.mdx) to read the schema from.

<details><summary>Usage Details</summary>

##### Mapping to Database Schemas

The name of the `schema` block represents the database schema to be created in the composed graph. For example, the
following schemas refer to the `public` and `private` schemas within a PostgreSQL database:

```hcl
data "composite_schema" "project" {
  schema "public" {
    url = ...
  }
  schema "private" {
    url = ...
  }
}
```

##### Schema Dependencies

The order of the `schema` blocks defines the order in which Atlas will load the schemas to compose the entire database
graph. This is useful in the case of dependencies between the schemas. For example, the following schemas refer to the
`inventory` and `auth` schemas, where the `auth` schema depends on the `inventory` schema and therefore should be loaded
after it:

```hcl
data "composite_schema" "project" {
  schema "inventory" {
    url = ...
  }
  schema "auth" {
    url = ...
  }
}
```

##### Schema Composition

Defining multiple `schema` blocks with the same name enables extending the same database schema from multiple sources.
For example, the following configuration shows how an ORM schema, which relies on database types that cannot be defined
within the ORM itself, can load them separately from another schema source that supports it:

```hcl
data "composite_schema" "project" {
  schema "public" {
    url = "file://types.pg.hcl"
  }
  schema "public" {
    url = "ent://ent/schema"
  }
}
```

</details>

##### Attributes {#data-source-composite-schema-attributes}

- `url` - The [URL](../concepts/url.mdx) of the composite schema.

#### Usage example

By running `atlas migrate diff` with the given configuration, Atlas loads the `inventory` schema from the [SQLAlchemy schema](/guides/orms/sqlalchemy),
the `graph` schema from [ent/schema](https://entgo.io), and the `auth` and `internal` schemas from HCL and SQL schemas defined in
Atlas format. Then, the composite schema, which represents these four schemas combined, will be compared against the
current state of the migration directory. In case of a difference between the two states, a new migration file will be
created with the necessary SQL statements.

```hcl title="atlas.hcl" {1-14}
data "composite_schema" "project" {
  schema "inventory" {
    url = data.external_schema.sqlalchemy.url
  }
  schema "graph" {
    url = "ent://ent/schema"
  }
  schema "auth" {
    url = "file://path/to/schema.hcl"
  }
  schema "internal" {
    url = "file://path/to/schema.sql"
  }
}

env "dev" {
  src = data.composite_schema.project.url
  dev = "docker://postgres/15/dev"
  migration {
    dir = "file://migrations"
  }
}
```

#### Data source: `remote_dir`

The `remote_dir` data source reads the state of a migration directory from [Atlas Cloud](https://atlasgo.cloud). For
instructions on how to connect a migration directory to Atlas Cloud, please refer to the [cloud documentation](../cloud/directory.mdx).

##### Arguments {#data-source-remote_dir-arguments}

- `name` - The name of the migration directory, as defined in Atlas Cloud.
- `tag` (optional) - The tag of the migration directory, such as Git commit. If not specified, the latest
tag (e.g., `master` branch) will be used.

##### Attributes {#data-source-remote_dir-attributes}

- `url` - A [URL](../concepts/url.mdx) to the loaded migration directory.

```hcl title="atlas.hcl" {6-21}
variable "database_url" {
  type    = string
  default = getenv("DATABASE_URL")
}

variable "cloud_token" {
  type    = string
  default = getenv("ATLAS_TOKEN")
}

atlas {
  cloud {
    token = var.cloud_token
  }
}

data "remote_dir" "migrations" {
  // The name of the migration directory in Atlas Cloud.
  // In this example, the directory is named "graph".
  name = "graph"
}

env {
  // Set environment name dynamically based on --env value.
  name = atlas.env
  url = var.database_url
  migration {
    dir = data.remote_dir.migrations.url
  }
}
```

#### Usage example

```shell
atlas migrate apply \
  --url "<DATABASE_URL>" \
  -c file://path/to/atlas.hcl \
  --env prod \
  --var cloud_token="<ATLAS_TOKEN>"
```

```shell
DATABASE_URL="<DATABASE_URL>" ATLAS_TOKEN="<ATLAS_TOKEN>" \
  atlas migrate apply \
  -c file://path/to/atlas.hcl \
  --env prod
```

:::info Reporting Cloud Deployments
In case the `cloud` block was activated with a valid token, Atlas logs migration runs in your cloud account
to facilitate the monitoring and troubleshooting of executed migrations. The following is a demonstration of how it
appears in action:

<details><summary>Screenshot example</summary>

![](https://atlasgo.io/uploads/cloud/images/full-deployment-example.png)

</details>

:::

#### Data source: `template_dir`

The `template_dir` data source renders a migration directory from a template directory. It does this by parsing the
entire directory as [Go templates](https://golang.org/pkg/text/template), executing top-level (template) files that
have the `.sql` file extension, and generating an in-memory migration directory from them.

##### Arguments {#data-source-template_dir-arguments}

- `path` - A path to the template directory.
- `vars` - A map of variables to pass to the template.

##### Attributes {#data-source-template_dir-attributes}

- `url` - A [URL](../concepts/url.mdx) to the generated migration directory.

<Tabs>
<TabItem label="Read only templates" value="read-only">

```hcl title="atlas.hcl" {6-14,19}
variable "path" {
  type        = string
  description = "A path to the template directory"
}

data "template_dir" "migrations" {
  path = var.path
  vars = {
    Key1 = "value1"
    Key2 = "value2"
    // Pass the --env value as a template variable.
    Env  = atlas.env
  }
}

env "dev" {
  url = var.url
  migration {
    dir = data.template_dir.migrations.url
  }
}
```

</TabItem>
<TabItem label="Variables shared between HCL and directory" value="diff">

```hcl title="atlas.hcl" {13-18,24}
variable "schema_name" {
  type    = string
  default = "Database schema name injected to both migrations directory and HCL schema"
}

data "hcl_schema" "app" {
  path = "path/to/schema.hcl"
  vars = {
    schema_name = var.schema_name
  }
}

data "template_dir" "migrations" {
  path = "path/to/directory"
  vars = {
    schema_name = var.schema_name
  }
}

env "local" {
  src = data.hcl_schema.app.url
  dev = "sqlite://file?mode=memory&_fk=1"
  migration {
    dir = data.template_dir.migrations.url
  }
}
```

</TabItem>
</Tabs>

#### Data source: `aws_rds_token`

The `aws_rds_token` data source generates a short-lived token for an [AWS RDS](https://aws.amazon.com/rds/) database
using [IAM Authentication](https://aws.github.io/aws-sdk-go-v2/docs/sdk-utilities/rds/#iam-authentication).

To use this data source:
1. Enable IAM Authentication for your database. For instructions on how to do this,
   [see the AWS documentation](https://aws.github.io/aws-sdk-go-v2/docs/sdk-utilities/rds/#iam-authentication).
2. Create a database user and grant it permission to authenticate using IAM, see
   [the AWS documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.DBAccounts.html)
   for instructions.
3. Create an IAM role with the `rds-db:connect` permission for the specific database and user. For instructions on how to do this,
   [see the AWS documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html).

##### Arguments {#data-source-aws_rds_token-arguments}

- `region` - The AWS region of the database (Optional).
- `endpoint` - The endpoint of the database (hostname:port).
- `username` - The database user to authenticate as.

##### Attributes {#data-source-aws_rds_token-attributes}

- The loaded variable is a `string` type with no attributes. Notice that the token contains special characters that
  need to be escaped when used in a URL. To escape the token, use the `urlescape` function.

##### Example

```hcl title="atlas.hcl"
locals {
  user = "iamuser"
  endpoint = "hostname-of-db.example9y7k.us-east-1.rds.amazonaws.com:5432"
}

data "aws_rds_token" "db" {
	region = "us-east-1"
	endpoint = local.endpoint
	username = local.user
}

env "rds" {
  url = "postgres://${local.user}:${urlescape(data.aws_rds_token.db)}@${local.endpoint}/postgres"
}
```

#### Data source: `gcp_cloudsql_token`

The `gcp_cloudsql_token` data source generates a short-lived token for an [GCP CloudSQL](https://cloud.google.com/sql) database
using [IAM Authentication](https://cloud.google.com/sql/docs/mysql/authentication#manual).

To use this data source:
1. Enable IAM Authentication for your database. For instructions on how to do this,
   [see the GCP documentation](https://cloud.google.com/sql/docs/mysql/create-edit-iam-instances).
2. Create a database user and grant it permission to authenticate using IAM, see
   [the GCP documentation](https://cloud.google.com/sql/docs/mysql/add-manage-iam-users)
   for instructions.

##### Attributes {#data-source-gcp_cloudsql_token-attributes}

- The loaded variable is a `string` type with no attributes. Notice that the token contains special characters that
  need to be escaped when used in a URL. To escape the token, use the `urlescape` function.

##### Example

```hcl title="atlas.hcl"
locals {
  user = "iamuser"
  endpoint = "34.143.100.1:3306"
}

data "gcp_cloudsql_token" "db" {}

env "rds" {
  url = "mysql://${local.user}:${urlescape(data.gcp_cloudsql_token.db)}@${local.endpoint}/?allowCleartextPasswords=1&tls=skip-verify&parseTime=true"
}
```
:::note
The `allowCleartextPasswords` and `tls` parameters are required for the MySQL driver to connect to CloudSQL. For PostgreSQL, use `sslmode=require` to connect to the database.
:::

### Environments

The `env` block defines an environment block that can be selected by using the `--env` flag.

##### Arguments {#environment-arguments}

- `for_each` - A meta-argument that accepts a map or a set of strings and is used to compute an `env` instance for each
set or map item. See the example [below](#multi-environment-example).

- `url` - The [URL](../concepts/url.mdx) of the target database.

- `dev` - The [URL](../concepts/url.mdx) of the [Dev Database](../concepts/dev.mdx).

- `schemas` - A list of strings defines the schemas that Atlas manages.

- `exclude` - A list of strings defines glob patterns used to filter resources on inspection.

- `migration` - A block defines the migration configuration of the env.
  - `dir` - The [URL](../concepts/url.mdx) to the migration directory.
  - `baseline` - An optional version to start the migration history from. Read more [here](../versioned/apply.mdx#existing-databases).
  - `exec_order` - Set the file execution order [`LINEAR` (default), `LINEAR_SKIP`, `NON_LINEAR`]. Read more [here](../versioned/apply.mdx#execution-order).
  - `lock_timeout` - An optional timeout to wait for a database lock to be released. Defaults to `10s`.
  - `revisions_schema` - An optional name to control the schema that the revisions table resides in.

- `format` - A block defines the formatting configuration of the env per command (previously named `log`).
  - `migrate`
    - `apply` - Set custom formatting for `migrate apply`.
    - `diff` - Set custom formatting for `migrate diff`.
    - `lint` - Set custom formatting for `migrate lint`.
    - `status` - Set custom formatting for `migrate status`.
  - `schema`
    - `apply` - Set custom formatting for `schema apply`.
    - `diff` - Set custom formatting for `schema diff`.

- `lint` - A block defines the migration linting configuration of the env.
  - `format` - Override the `--format` flag by setting a custom logging for `migrate lint` (previously named `log`).
  - `latest` - A number configures the `--latest` option.
  - `git.base` - A run analysis against the base Git branch.
  - `git.dir` - A path to the repository working directory.
  - `review` - The policy to use when deciding whether the user should be prompted to review and approve the changes.
    Currently works with declarative migrations and requires the user to log in. Supported options:
    - `ALWAYS` - Always prompt the user to review and approve the changes.
    - `WARNING` - Prompt if any diagnostics are found.
    - `ERROR` - Prompt if any severe diagnostics (errors) are found.  By default this will happen on destructive changes only.

- `diff` - A block defines the schema diffing policy.

##### Multi Environment Example

Atlas adopts the `for_each` meta-argument that [Terraform uses](https://www.terraform.io/language/meta-arguments/for_each)
for `env` blocks. Setting the `for_each` argument will compute an `env` block for each item in the provided value. Note
that `for_each` accepts a map or a set of strings.

<Tabs>
<TabItem value="versioned" label="Versioned Migration" default>

```hcl title="atlas.hcl"
env "prod" {
  for_each = toset(data.sql.tenants.values)
  url      = urlsetpath(var.url, each.value)
  migration {
    dir = "file://migrations"
  }
  format {
    migrate {
      apply = format(
        "{{ json . | json_merge %q }}",
        jsonencode({
          Tenant : each.value
        })
      )
    }
  }
}
```

</TabItem>
<TabItem value="declarative" label="Declarative Migration">

```hcl title="atlas.hcl"
env "prod" {
  for_each = toset(data.sql.tenants.values)
  url      = urlsetpath(var.url, each.value)
  src      = "schema.hcl"
  format {
    schema {
      apply = format(
        "{{ json . | json_merge %q }}",
        jsonencode({
          Tenant : each.value
        })
      )
    }
  }
  // Inject custom variables to the schema.hcl defined below.
  tenant = each.value
}
```

```hcl title="schema.hcl"
variable "tenant" {
  type        = string
  description = "The schema we operate on"
}

schema "tenant" {
  name = var.tenant
}

table "users" {
  schema = schema.tenant
  // ...
}
```

</TabItem>
</Tabs>

## Configure Migration Linting

Project files may declare `lint` blocks to configure how migration linting runs in a specific environment or globally.

```hcl
lint {
  destructive {
    // By default, destructive changes cause migration linting to error
    // on exit (code 1). Setting `error` to false disables this behavior.
    error = false
  }
  // Custom logging can be enabled using the `format` attribute (previously named `log`).
  format = <<EOS
{{- range $f := .Files }}
	{{- json $f }}
{{- end }}
EOS
}

env "local" {
  // Define a specific migration linting config for this environment.
  // This block inherits and overrides all attributes of the global config.
  lint {
    latest = 1
  }
}

env "ci" {
  lint {
    git {
      base = "master"
      // An optional attribute for setting the working
      // directory of the git command (-C flag).
      dir = "<path>"
    }
  }
}
```

## Configure Diff Policy

Project files may define `diff` blocks to configure how schema diffing runs in a specific environment or globally.


```hcl
diff {
  skip {
    // By default, none of the changes are skipped.
    drop_schema = true
    drop_table  = true
  }
  concurrent_index {
    create = true
    drop   = true
  }
}

env "local" {
  // Define a specific schema diffing policy for this environment.
  diff {
    skip {
      drop_schema = true
    }
  }
}
```
